/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cdp.web.component.metadata.serializer;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.inspur.edp.caf.cef.schema.base.utils.JsonUtil;
import com.inspur.edp.cdp.cdf.component.manager.serializer.CompOperationSerializer;
import com.inspur.edp.cdp.cdf.component.manager.serializer.ComponentSerializer;
import com.inspur.edp.cdp.web.component.metadata.ComponentConstant;
import com.inspur.edp.cdp.web.component.metadata.define.Operation;
import com.inspur.edp.cdp.web.component.metadata.define.Parameter;
import com.inspur.edp.cdp.web.component.metadata.define.WebComponentMetadata;
import com.inspur.edp.component.schema.AbstractComponent;

/**
 * @author Kaixuan Shi
 * @version 0.1
 */
public class WebComponentMetadataSerializer extends ComponentSerializer {

    //此字段用于标识新版数据版本，反序列化时使用，尤其是后续再次进行更新时，能够用来判断元数据结构版本
    private static final String CLASS_VERSION = "v2.0";

    @Override
    protected void readExtendInfo(AbstractComponent abstractComponent, JsonNode jsonNode) {
        WebComponentMetadata webComponent = (WebComponentMetadata) abstractComponent;
        if (JsonUtil.isExistsProp(jsonNode, ComponentConstant.CLASS_VERSION)) {
            if (JsonUtil.isExistsProp(jsonNode, ComponentConstant.IS_COMMON)) {
                webComponent.setCommon(JsonUtil.getPropValue(jsonNode, ComponentConstant.IS_COMMON, boolean.class));
            }
            webComponent.setFormCode(JsonUtil.getPropValue(jsonNode, ComponentConstant.FORM_CODE, String.class));
        } else {//旧版数据结构需特殊处理，需反序列化整全部内容
            this.readOldStructure(webComponent, jsonNode);
        }
    }

    @Override
    protected void writeExtendInfo(AbstractComponent abstractComponent, JsonNode jsonNode) {
        WebComponentMetadata webComponent = (WebComponentMetadata) abstractComponent;
        JsonUtil.setPropValue(jsonNode, ComponentConstant.IS_COMMON, webComponent.isCommon());
        JsonUtil.setPropValue(jsonNode, ComponentConstant.FORM_CODE, webComponent.getFormCode());
        JsonUtil.setPropValue(jsonNode, ComponentConstant.CLASS_VERSION, CLASS_VERSION);
    }

    @Override
    protected CompOperationSerializer getOperationSerializer() {
        return new OperationSerializer();
    }

    @Override
    protected AbstractComponent createComponent() {
        return new WebComponentMetadata();
    }

    private void readOldStructure(WebComponentMetadata webComponent, JsonNode compNode) {
        webComponent.setId(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.ID, String.class));
        webComponent.setCode(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.CODE, String.class));
        webComponent.setDescription(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.DESCRIPTION, String.class));
        webComponent.setSource(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.SOURCE, String.class));
        if (JsonUtil.isExistsProp(compNode, ComponentConstant.oldComponentField.IS_COMMON)) {
            webComponent.setCommon(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.IS_COMMON, boolean.class));
        }
        webComponent.setClassName(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.CLASS_NAME, String.class));
        webComponent.setFormCode(JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.FORM_CODE, String.class));
        this.readOldStructureOperation(webComponent, compNode);
    }

    private void readOldStructureOperation(WebComponentMetadata webComponent, JsonNode compNode) {
        ArrayNode opArray = JsonUtil.getPropValue(compNode, ComponentConstant.oldComponentField.OPERATIONS, ArrayNode.class);
        if (opArray == null || opArray.isEmpty()) {
            return;
        }
        for (JsonNode opNode : opArray) {
            Operation operation = new Operation();
            operation.setId(JsonUtil.getPropValue(opNode, ComponentConstant.oldOperationField.ID, String.class));
            operation.setCode(JsonUtil.getPropValue(opNode, ComponentConstant.oldOperationField.CODE, String.class));
            operation.setName(JsonUtil.getPropValue(opNode, ComponentConstant.oldOperationField.NAME, String.class));
            operation.setDescription(JsonUtil.getPropValue(opNode, ComponentConstant.oldOperationField.DESCRIPTION, String.class));
            this.readOldStructureParameter(operation, opNode);
            webComponent.addOperation(operation);
        }

    }

    private void readOldStructureParameter(Operation operation, JsonNode opNode) {
        ArrayNode paramArray = JsonUtil.getPropValue(opNode, ComponentConstant.oldOperationField.PARAMETERS, ArrayNode.class);
        if (paramArray == null || paramArray.isEmpty()) {
            return;
        }
        for (JsonNode paramNode : paramArray) {
            Parameter parameter = new Parameter();
            parameter.setId(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.ID, String.class));
            parameter.setCode(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.CODE, String.class));
            parameter.setName(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.NAME, String.class));
            parameter.setDescription(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.DESCRIPTION, String.class));
            parameter.setParamType(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.ParamType, String.class));
            if (JsonUtil.isExistsProp(paramNode, ComponentConstant.oldParameterField.IS_RET_VAL)) {
                parameter.setRetVal(JsonUtil.getPropValue(paramNode, ComponentConstant.oldParameterField.IS_RET_VAL, boolean.class));
            }
            operation.addParameter(parameter);
        }
    }
}
